package flc.ast.utils;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.blankj.utilcode.util.ToastUtils;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UDPClient {
    // 回调接口（保持与TCPClient兼容）
    public interface ClientListener {
        void onConnected();

        void onConnectionFailed(String error);

        void onDisconnected();

        void onMessageReceived(String message);

        void onError(String error);

        void onStatisticsUpdated(int receivedCount, int sentCount, double receiveSpeed, double sendSpeed, int failedCount);
    }

    private ClientListener listener;
    private Handler mainHandler = new Handler(Looper.getMainLooper());
    private DatagramSocket socket;
    private InetAddress serverAddress;
    private int serverPort;
    private String receiveCharsetName = "UTF-8";
    private String sendCharsetName = "UTF-8";
    private ExecutorService executor = Executors.newSingleThreadExecutor();
    private boolean isRunning = false;
    private int bufferSize = 1024; // UDP接收缓冲区大小

    // 统计信息（与TCPClient保持一致）
    private int receivedCount = 0;
    private int sentCount = 0;
    private long receivedBytes = 0;
    private long sentBytes = 0;
    private long startTime = 0;
    private int failedCount = 0;

    public void setClientListener(ClientListener listener) {
        this.listener = listener;
    }

    public void setReceiveCharsetName(String charsetName) {
        if (charsetName != null && !charsetName.isEmpty()) {
            this.receiveCharsetName = charsetName;
        }
    }

    public void setSendCharsetName(String charsetName) {
        if (charsetName != null && !charsetName.isEmpty()) {
            this.sendCharsetName = charsetName;
        }
    }

    public boolean isConnected() {
        return socket != null && !socket.isClosed() && isRunning;
    }

    // UDP连接实际只是初始化Socket并保存服务器地址（无实际连接过程）
    public void connect(String serverIp, int port) {
        executor.execute(() -> {
            try {
                // 解析服务器地址
                serverAddress = InetAddress.getByName(serverIp);
                serverPort = port;

                // 创建UDP Socket（不绑定固定端口则系统自动分配）
                socket = new DatagramSocket();
                socket.setSoTimeout(1000); // 设置接收超时，避免阻塞
                isRunning = true;
                startTime = System.currentTimeMillis();

                // 启动接收线程
                startReceiveThread();

                // 通知连接成功（UDP无握手，此处为逻辑连接）
                notifyConnected();
            } catch (UnknownHostException e) {
                failedCount++;
                notifyConnectionFailed("未知主机: " + e.getMessage());
                updateStatistics();
            } catch (SocketException e) {
                failedCount++;
                notifyConnectionFailed("Socket创建失败: " + e.getMessage());
                updateStatistics();
            }
        });
    }

    // 启动单独线程接收UDP数据包
    private void startReceiveThread() {
        executor.execute(() -> {
            byte[] buffer = new byte[bufferSize];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

            while (isRunning && !socket.isClosed()) {
                try {
                    socket.receive(packet);
                    // 验证数据包是否来自目标服务器
                    if (packet.getAddress().equals(serverAddress) && packet.getPort() == serverPort) {
                        String message = new String(packet.getData(), 0, packet.getLength(), Charset.forName(receiveCharsetName));
                        String senderInfo = "[" + packet.getAddress().getHostAddress() + ":" + packet.getPort() + "]";
                        final String fullMessage = senderInfo + message;

                        // 更新统计信息
                        receivedCount++;
                        receivedBytes += packet.getLength();
                        notifyMessageReceived(fullMessage);
                        updateStatistics();
                    }
                } catch (IOException e) {
                    // 超时异常属于正常现象，不视为错误
                    if (!(e instanceof java.net.SocketTimeoutException)) {
                        if (isRunning) {
                            failedCount++;
                            notifyError("接收失败: " + e.getMessage());
                            updateStatistics();
                        }
                    }
                }
            }
        });
    }

    // 发送UDP消息
    public void sendMessage(String message) {
        if (!isConnected() || serverAddress == null) {
            notifyError("未连接到服务器");
            return;
        }

        new Thread(()->{
            try {
                byte[] data = message.getBytes(Charset.forName(sendCharsetName));
                DatagramPacket packet = new DatagramPacket(data, data.length, serverAddress, serverPort);
                socket.send(packet);

                // 更新统计信息
                sentCount++;
                sentBytes += data.length;
                updateStatistics();
            } catch (IOException e) {
                failedCount++;
                notifyError("发送失败: " + e.getMessage());
                updateStatistics();
            }
        }).start();
    }

    // 断开连接（关闭Socket并停止接收线程）
    public void disconnect() {
        if (!isRunning) return;

        isRunning = false;
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
        executor.shutdown();
        notifyDisconnected();
    }

    // 以下为回调通知方法（与TCPClient保持一致）
    private void notifyConnected() {
        mainHandler.post(() -> {
            if (listener != null) listener.onConnected();
        });
    }

    private void notifyConnectionFailed(final String error) {
        mainHandler.post(() -> {
            if (listener != null) listener.onConnectionFailed(error);
        });
    }

    private void notifyDisconnected() {
        mainHandler.post(() -> {
            if (listener != null) listener.onDisconnected();
        });
    }

    private void notifyMessageReceived(final String message) {
        mainHandler.post(() -> {
            if (listener != null) listener.onMessageReceived(message);
        });
    }

    private void notifyError(final String error) {
        mainHandler.post(() -> {
            if (listener != null) listener.onError(error);
        });
    }

    private void updateStatistics() {
        if (listener == null) return;

        long currentTime = System.currentTimeMillis();
        double elapsedTime = (currentTime - startTime) / 1000.0;

        double receiveSpeed = elapsedTime > 0 ? receivedBytes / elapsedTime : 0;
        double sendSpeed = elapsedTime > 0 ? sentBytes / elapsedTime : 0;

        mainHandler.post(() -> {
            listener.onStatisticsUpdated(receivedCount, sentCount, receiveSpeed, sendSpeed, failedCount);
        });
    }
}